package com.work.dao.impl;

import com.work.dao.DBDao;
import com.work.utils.JDBCUtil;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by Administrator on 2017/9/29.
 */
public class DBImpl implements DBDao {

    private List getListBySet(ResultSet set, String tableName) {

        List list = new ArrayList();

        Class c = list.getClass();

        try {

            while (set.next()) {

                Method method = c.getMethod("add", Object.class);
                method.invoke(list, getO(set, tableName));
            }

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return list;
    }

    @Override
    public List find(String sql, String tableName) {

        List list = new ArrayList();
        try {
            Connection connection = JDBCUtil.getConnection();
            Statement statement = connection.createStatement();

            System.out.println(sql);
            ResultSet set = statement.executeQuery(sql);

            list = getListBySet(set, tableName);

            JDBCUtil.close(connection, statement, set);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return list;
    }


    @Override
    public HashMap<Integer, List> page(int countPage, int whichPage,
                                       String sql, String tableName) {

        HashMap<Integer, List> map = new HashMap<Integer, List>();

        Connection connection = null;
        int pageNumber = 0;

        List list = new ArrayList();
        try {
            Class c = list.getClass();

            connection = JDBCUtil.getConnection();
            Statement statement = connection.createStatement(
                    ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            ResultSet set = statement.executeQuery(sql);
            set.last();
            int totalCount = set.getRow();

            if (totalCount > 0) {

                pageNumber = (int) Math.ceil((float) totalCount / Float.valueOf(countPage));

                int start = (whichPage - 1) * countPage + 1;
                int end = (totalCount <= start + countPage ? totalCount : start
                        + countPage);

                set.absolute(start);
                statement.setMaxRows(end);

                outer:
                for (int i = 0; i < countPage; i++) {

                    if (set.isAfterLast()) {

                        break outer;

                    } else {

                        Method method = c.getMethod("add", Object.class);
                        method.invoke(list,getO(set, tableName));
                        set.next();
                    }
                }
            }
            JDBCUtil.close(connection, statement, set);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        System.out.println(list.size());
        map.put(pageNumber, list);
        return map;
    }


    private Object getO(ResultSet set, String tableName) {

        Class entities;
        Object o = null;
        try {
            entities = Class.forName(tableName);

            Constructor[] constructors = entities.getDeclaredConstructors();
            Field[] fields = entities.getDeclaredFields();

            List<Object> objects = new ArrayList<Object>();
            for (Field field : fields) {
                if (field.getType().getSimpleName().equals("int")) {
                    objects.add(set.getInt(field.getName()));
                } else if (field.getType().getSimpleName().equals("String")) {
                    objects.add(set.getString(field.getName()));
                }
            }
            for (int j = 0; j < constructors.length; j++) {
                if (constructors[j].getParameterTypes().length == fields.length) {
                    o = constructors[j].newInstance(objects.toArray());
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return o;

    }


    @Override
    public boolean insertAndDelAndUpdate(String sql) {

        System.out.println(sql);

        Connection connection = null;

        System.out.println(sql);

        try {
            connection = JDBCUtil.getConnection();
            Statement statement = connection.createStatement();

            if (statement.executeUpdate(sql) > 0) {

                JDBCUtil.close(connection, statement, null);

                return true;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }
}
